var LB = LB || {};

LB.Auth = {};
LB.Sync = {};
LB.Utils = {};
LB.DB = {};


LB.Book = {};
LB.Book.currentPage = 0;
LB.Book.numPages = 0;
LB.Book.pages = [];

LB.Book.newPage = function () {
  var page = new Page();
  this.pages.push(page);
  this.numPages++;
  $("#pagenum").html("Page: " + (this.currentPage+1) + " of " + this.numPages);
};

LB.Book.pushObject = function (o) {
  this.pages[this.currentPage].pushObj(o);
};

LB.Book.removeObjFromCurrPage = function () {
  return this.pages[this.currentPage].popObj();
};

LB.Book.redrawCurrPage = function () {
  this.pages[this.currentPage].redraw();
};

LB.Book.getObjectsCurrPage = function () {
  return this.pages[this.currentPage].objects;
};

LB.Book.setObjectsCurrPage = function (str) {
  var objs = JSON.parse(str);
  this.pages[this.currentPage].restore(objs);
};

LB.Book.prevPage = function() {
  if(this.currentPage === 0) {
    return;
  }
  $("#canvas_id").hide();
  this.currentPage--;
  this.redrawCurrPage();
  $("#canvas_id").show("slide", "slow");
  $("#pagenum").html("Page: " + (this.currentPage+1) + " of " + this.numPages);
};

LB.Book.nextPage = function() {
  //if its last page and next is pressed, add a new page
  if(this.currentPage === this.numPages-1) {
    //if nothing is drawn dont add a page
    if (this.pages[this.currentPage].objects.length != 0) {
      this.newPage();
    }
    else {
      LB.UI.message("You already have a blank page", 1000);
      return;
    }
  }
  $("#canvas_id").hide();
  this.currentPage++;
  this.redrawCurrPage();
  $("#canvas_id").show("slide", {direction: 'right'}, "slow");
  $("#pagenum").html("Page: " + (this.currentPage+1) + " of " + this.numPages);
};

LB.Book.gotoPage = function(pagenum) {
  if(pagenum > this.numPages) {
    LB.UI.alert("No such page number: " + pagenum);
    return;
  }
  $("#canvas_id").hide();
  this.currentPage = pagenum-1;
  this.redrawCurrPage();
  $("#canvas_id").show("slide", "slow");
  $("#pagenum").html("Page: " + (this.currentPage+1) + " of " + this.numPages);
};

LB.Book.resetCurrPage = function () {
  this.pages[this.currentPage].reset();
  this.redrawCurrPage();
};

LB.Book.undo = function () {
  this.pages[this.currentPage].undo();
  this.redrawCurrPage();
};

LB.Book.redo = function () {
  this.pages[this.currentPage].redo();
  this.redrawCurrPage();
};

LB.Book.saveCurrPage = function(pagename) {
  //save the currentPage in DB
  var jsonstr = JSON.stringify(this.pages[this.currentPage].objects);
  LB.DB.savePage(this.currentPage, pagename, jsonstr, this.numPages);
}

LB.Book.loadPage = function(str, pagenum) {
  var objs = JSON.parse(str);
  this.pages[pagenum].restore(objs);
}

//--------------- Canvas ----------------
LB.Canvas = {};
LB.UI = {};

LB.Canvas.Events = {};

LB.Canvas.initCanvas = function () {
  var can, width, height;
  can = document.getElementById("canvas_id");
  cctx = can.getContext("2d");
  $("#canvas_id").mousedown(this.Events.mousedown);
  $("#canvas_id").mousemove(this.Events.mousemove);
  $("#canvas_id").mouseup(this.Events.mouseup);
  $("#canvas_id").bind('touchstart', this.Events.touchstart);
  $("#canvas_id").bind('touchmove', this.Events.touchmove);
  $("#canvas_id").bind('touchend', this.Events.touchend);
  //$("#canvas_id").bind('taphold', function(){alert("taphold");});
  $("#canvas_id").mouseleave(this.Events.mouseleave);
  $("#canvas_id").dblclick(this.Events.dblclick);

  width = settings.width.toString();
  height = settings.height.toString();
  can.width = width;
  can.height = height;
  $("#canvasarea").css('width', width);
  $("#canvasarea").css('height', height);
  
  settings.bgColor = $("body").css('backgroundColor');
  //if no color is set make it white
  if(settings.bgColor === "rgba(0, 0, 0, 0)") {
    settings.bgColor = "#fff";
  }

  cctx.strokeStyle = settings.strokeStyle;
  cctx.lineWidth = settings.lineWidth;
  cctx.globalAlpha = 1.0;
  cctx.strokeRect(50.5, 50.5, settings.gridsize, settings.gridsize);

  //default font settings
  cctx.textBaseline = "middle";
  //cctx.fillStyle = settings.strokeStyle;
  cctx.fillStyle = "#333";
  cctx.font = "26px sans-serif";

  LB.Book.newPage();
  LB.Canvas.redrawCanvas();
  writeDebug("initCanvas: created canvas ctx = " + cctx, 5);
};


LB.Canvas.redrawCanvas = function () {
  var i = 0;
  var j = 1;
  var blen = boxes.length;

  writeDebug("redrawCanvas: " + boxes.length, 6);

  /*
  for(i=0; i<blen; i++) {
    //redraw the box only if its inuse.
    if(boxes[i].inuse === 1) {
      boxes[i].redraw();
    }
  }
  */
  LB.Book.redrawCurrPage();

};


LB.Canvas.reset = function() {
  writeDebug("Resetting Canvas", 5);
  LB.Book.resetCurrPage();

};


LB.Canvas.restore = function() {
  var sb = [];
  var objs = [];
  var i = 0;
  var p;
  //nothing saved yet
  if( (g_ObjsJson === "") && (bboxjson === "") ) {
    return;
  }
  var objs = JSON.parse(g_ObjsJson);
  //var sb = JSON.parse(bboxjson);
  var sb = [];
  var sblen = sb.length;
  var len = objs.length;

  //reset existing paths and boxes array
  LB.Canvas.reset();

  for(i=0; i<sblen; i++) {
    var b = get_bbox();
    b.create(sb[i].xmin, sb[i].ymin, sb[i].worig, sb[i].horig);
    b.path = sb[i].path;
  }

  for(i=0; i<len; i++) {
    if(objs[i].objname === "Path") {
      p = new Path();
      p.path = objs[i].path;
      p.strokeStyle = objs[i].strokeStyle;
      p.lineWidth = objs[i].lineWidth;
      LB.Book.pushObject(p);
    }
    else if(objs[i].objname === "Text") {
      var t = new Text();
      t.x = objs[i].x;
      t.y = objs[i].y;
      t.fillStyle = objs[i].strokeStyle;
      t.font = objs[i].font;
      t.text = objs[i].text;
      LB.Book.pushObject(t);
    }
  }
  LB.Canvas.redrawCanvas();
};

LB.Canvas.getSettings = function() {
  var rval = $("input[@name=flag_radio]:checked").val();
  if(rval === "erase") {
      eraseflag = 1;
      drawflag = 0;
      textflag = 0;
  }
  else if(rval === "draw") {
      eraseflag = 0;
      drawflag = 1;
      textflag = 0;
  }
  else if(rval === "text") {
      eraseflag = 0;
      drawflag = 0;
      textflag = 1;
  }
  rval = $("input[name=slider]").val();
  settings.lineWidth = rval;
};

LB.Canvas.Events.pendown = function(pt) {
  var len = boxes.length;
  var i = 0;

  if(chatdown === 1) {
    $("#chatarea").hide();
    chatdown = 0;
  }
  $("#skypearea").hide();

  //bbox has a greater area than the path, due to gui elements and resize anchors etc.
  //so if a box is selected as indicated by selected flag
  //then we need to check for a larger area and pass the event to the bbox
  if(selected >= 0) {
      if(boxes[selected].isBBoxSelected(pt.X, pt.Y)) {
        writeDebug("pendown: a bbox at index " + selected + " is selected", 5);
        boxes[selected].pendown(pt);
        return;
      }
  }

  //reset selected flag when pendown so that we can find
  //if a bbox is selected
  selected = -1;

  writeDebug("pendown: " + pt.X + " " + pt.Y, 5);

  if(settings.boxmode) {
    for(i=0; i<len; i++) {
      if(boxes[i].removed === 0 && boxes[i].inuse === 1) {
        writeDebug("pendown: selected to " + i + "from " + selected, 5);
        if(boxes[i].isPathSelected(pt.X, pt.Y)) {
          writeDebug("pendown: changing selected to " + i + "from " + selected, 5);
          selected = i;
          writeDebug("pendown: a path at index " + i + " was selected id: " + boxes[i].id, 5);
          //break;
        }
        else {
          //unhighlight other boxes
          boxes[i].unhighlight();
        }
      }
    }
    LB.Canvas.redrawCanvas();
  }

  LB.Canvas.getSettings();
  if(eraseflag === 1) {
    cctx.strokeStyle = settings.bgColor;
    cctx.lineWidth = settings.eraseWidth;
  }
  else if(drawflag === 1) {
    cctx.strokeStyle = settings.strokeStyle;
    cctx.lineWidth = settings.lineWidth;
  }
  else if(textflag === 1) {
    LB.UI.ctrlTextBox(0, 0, 0);
    LB.UI.ctrlTextBox(pt.X, pt.Y, 1);
    return;
  }
  else {
    //should not come here because of radio toggle of above
    //flag options
    alert("select atleast one mode 'Text|Draw|Erase'");
    return;
  }

  //if a bounding box is selected pass on the event to it
  //otherwise it means that we are going to draw/erase now
  //selected >=0 also indicates that boxmode is enabled.
  if(selected >= 0) {
      boxes[selected].pendown(pt);
  }
  else if(drawflag === 1 || eraseflag === 1) {
    pendownflag = 1;
    cctx.beginPath();
    cctx.moveTo(pt.X, pt.Y);
    currpath = [];
    currpath.push(pt);
    //reset the min/max to pendown point and zero
    xmin = pt.X;
    ymin = pt.Y;
    xmax = 0;
    ymax = 0;
  }
};

LB.Canvas.Events.penmove = function(pt) {
  if(selected >= 0) {
    boxes[selected].penmove(pt);
  }
  else {
    if(pendownflag === 1) {
      writeDebug("penmove: free draw" + pt.X + " " + pt.Y, 9);
      if(eraseflag === 1) {
        cctx.clearRect(pt.X, pt.Y, settings.eraseWidth, settings.eraseWidth);
      }
      else if(drawflag === 1) { 
        cctx.lineTo(pt.X, pt.Y);
        cctx.stroke();
      }

      //find bounding x y
      if (pt.X < xmin) {
        xmin = pt.X;
      }
      if (pt.X > xmax) {
        xmax = pt.X;
      }
      if (pt.Y < ymin) {
        ymin = pt.Y;
      }
      if (pt.Y > ymax) {
        ymax = pt.Y;
      }
      dragged = 1;
      currpath.push(pt);
    }
  }
};

LB.Canvas.Events.penup = function(pt) {
  var p;

  writeDebug("penup: " + pt.X + " " + pt.Y + " selected " + selected + " pendownflag=" + pendownflag, 5);

  //bbox selected, send the penup to the box
  if(selected >= 0) {
    boxes[selected].penup(pt);
  }
  else { //free drawing
    pendownflag = 0;
    if(dragged === 1) {
      dragged = 0;
      cctx.closePath();
      //detect shape
      //XXX

      if(settings.boxmode) {
        //create bbox
        var b = get_bbox();
        b.create(xmin, ymin, xmax-xmin, ymax-ymin);
        b.path = currpath.splice(0);
        b.strokeStyle = cctx.strokeStyle;
        b.lineWidth = cctx.lineWidth;
        writeDebug("penup: changing selected to " + b.id + " from " + selected, 5);
        selected = b.id;

        var data = {
          'type': 'bbox',
          'flag': 'new',
          'id': b.id,
          'groupname': groupname,
          'username': username,
          'gid': gid,
          'uid': uid,
          'box': b
        }
        if(wsock) {
          wsock.send(JSON.stringify(data));
        }
      }
      else if(settings.pathmode) {
        p = new Path();
        p.path = currpath.splice(0);
        p.strokeStyle = cctx.strokeStyle;
        p.lineWidth = cctx.lineWidth;
        if(eraseflag === 1) {
          p.erase = 1;
        }
        LB.Book.pushObject(p);

        var data = {
          'type': 'path',
          'flag': 'new',
          'groupname': groupname,
          'username': username,
          'gid': gid,
          'uid': uid,
          'path': p
        }
        if(wsock) {
          wsock.send(JSON.stringify(data));
        }
      }
    }
  }
};


LB.Canvas.Events.reset = function() {
  var data = {
    'type': 'bbox',
    'flag': 'reset',
    'groupname': groupname,
    'username': username,
    'gid': gid,
    'uid': uid
  }
  if(wsock) {
    wsock.send(JSON.stringify(data));
  }

  delDB(0);
  LB.Canvas.reset();
};

LB.Canvas.Events.undo = function() {
    var data = {
    'type': 'path',
    'flag': 'undo',
    'groupname': groupname,
    'username': username,
    'gid': gid,
    'uid': uid
  }

  if(wsock) {
    wsock.send(JSON.stringify(data));
  }

  LB.Book.undo();
};

LB.Canvas.Events.redo = function() {
  var data = {
    'type': 'path',
    'flag': 'redo',
    'groupname': groupname,
    'username': username,
    'gid': gid,
    'uid': uid
  }

  if(wsock) {
    wsock.send(JSON.stringify(data));
  }

  LB.Book.redo();
};

LB.Canvas.Events.next = function() {
  LB.Book.nextPage();
};

LB.Canvas.Events.prev = function() {
  LB.Book.prevPage();
};

LB.Canvas.Events.mousedown = function(e) {
  writeDebug("mousedown: " + e.pageX + " " + e.pageY, 9);
  var pt = {
    'X' : e.pageX - this.offsetLeft, 
    'Y' : e.pageY - this.offsetTop
  }
  LB.Canvas.Events.pendown(pt);
};

LB.Canvas.Events.touchstart = function(e) {
  e.preventDefault();
  var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  writeDebug("touchstart: " + touch.pageX + " " + touch.pageY, 5);
  var pt = {
    'X' : touch.pageX - this.offsetLeft, 
    'Y' : touch.pageY - this.offsetTop
  }
  LB.Canvas.Events.pendown(pt);
};


LB.Canvas.Events.mousemove = function(e) {
  writeDebug("mousemove: " + e.pageX + " " + e.pageY, 9);
  var pt = {
    'X' : e.pageX - this.offsetLeft, 
    'Y' : e.pageY - this.offsetTop
  }
  LB.Canvas.Events.penmove(pt); 
};


LB.Canvas.Events.touchmove = function(e) {
  e.preventDefault();
  var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  writeDebug("touchmove: " + e.originalEvent.touches[0].pageX + " " + e.originalEvent.touches[0].pageY, 9);
  var pt = {
    'X' : touch.pageX - this.offsetLeft,
    'Y' : touch.pageY - this.offsetTop
  }
  LB.Canvas.Events.penmove(pt); 
};


LB.Canvas.Events.mouseup = function(e) {
  writeDebug("mouseup: " + e.pageX + " " + e.pageY, 9);
  var pt = {
    'X' : e.pageX - (this.offsetLeft + this.parentNode.offsetLeft), 
    'Y' : e.pageY - (this.offsetTop + this.parentNode.offsetTop)
  }
  LB.Canvas.Events.penup(pt); 
};


LB.Canvas.Events.touchend = function(e) {
  e.preventDefault();
  var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
  writeDebug("touchend: " + touch.pageX + " " + touch.pageY, 5);
  var pt = {
    'X' : touch.pageX - this.offsetLeft,
    'Y' : touch.pageY - this.offsetTop
  }
  LB.Canvas.Events.penup(pt); 
};


LB.Canvas.Events.mouseleave = function(e) {
  if(pendownflag === 1) {
    pendownflag = 0;
  }
  writeDebug("mouseleave: " + e.pageX + " " + e.pageY, 8);
};


LB.Canvas.Events.dblclick = function(e) {
  alert("dblclick");
  e.preventDefault();
  writeDebug("dblclick: avoid", 5);
};


//********** UI functions ***********
LB.UI.initUI = function() {
  var tb_offset, offset;
  //$("#settings_page").css('left', width+100);
  //$("#settings_page").css('height', height);
  
  tb_offset = $("#toolbar").offset();
  $("#settingpanel").css('right', '4em');
  var can_height = $("#canvasarea").css('height');
  $("#settingpanel").css('top', tb_offset.top-220);
  $("#settingpanel").css('width', '30%');

  //XXX user touchstart events for iphone/ipad
  $("#reset_btn").bind('vclick', LB.Canvas.Events.reset);
  $("#setting_btn").bind('vclick', function() {setting_btn();});
  $("#chat_btn").bind('vclick', chat);
  $("#skype_btn").bind('vclick', skype);
  $("#chat_send_btn").bind('click', chat_send);
  $("#debug_btn").bind('vclick', debug);
  $("#save_btn").bind('vclick', LB.UI.savedialog());
  LB.UI.ctrlTextBox(0, 0, 0); //close it initially

  //paging
  //$("#prev_btn").bind('vclick', function() {
  //                  LB.Book.prevPage()});
  //$("#next_btn").bind('vclick', function() {
  //                  LB.Book.nextPage()});

  $("#prev_btn").bind('vclick', LB.Canvas.Events.prev);
  $("#next_btn").bind('vclick', LB.Canvas.Events.next);
  $("#undo_btn").bind('vclick', LB.Canvas.Events.undo);
  $("#redo_btn").bind('vclick', LB.Canvas.Events.redo);

  $("#chatarea").hide();
  $("#skypearea").hide();
  $("#debugarea").hide();
  $("#settingpanel").hide();

  offset = $("#header").css("height");
  $("#chatarea").css('top', offset);
  $("#skypearea").css('top', 78);
  $("#chatarea").css('left', 1);
  $("#skypearea").css('left', 1);
  $("#chatoutput").css('height', (settings.height/1.5));

  //color palette
  $("#c_selected").css("background-color", settings.strokeStyle);
  $("#c_default").css("background-color", settings.strokeStyle);

  $('#c_red, #c_green, #c_orange, #c_black, \
    #c_yellow, #c_blue, #c_brown, #c_grey, \
    #c_white, #c_default').bind("vclick", function () {
        var c_id = $(this).attr("id");
        var clr = $(this).css('background-color');
        $("#c_selected").css("background-color", clr);
        settings.strokeStyle = clr;
  });

};

LB.UI.ctrlTextBox = function(x, y, open) {
  if(open === 1) {
    $("#textbox").css('left', x+180);
    $("#textbox").css('top', y+100);
    $("#textbox").show();
    $("#write_btn").bind('click', 
                    function() {
                      LB.UI.writeTextBox(x, y);
                    });
    $("#cancel_btn").bind('click', 
                    function() {
                      LB.UI.ctrlTextBox(x, y, 0);
                    });
  }
  else {
    $("#write_btn").unbind('click');
    $("#cancel_btn").unbind('click');
    $("#textbox").hide();
  }
};


LB.UI.writeTextBox = function(x, y) {
  //close textbox dialog and write the text string.
  LB.UI.ctrlTextBox(0, 0, 0); 

  var str = $("#text_input").val();
  var t = new Text();
  t.x = x;
  t.y = y;
  t.fillStyle = settings.strokeStyle;
  t.text = str;
  t.drawObj();
  LB.Book.pushObject(t);

  var data = {
    'type': 'text',
    'flag': 'new',
    'groupname': groupname,
    'username': username,
    'gid': gid,
    'uid': uid,
    'text': t
  }
  if(wsock) {
    wsock.send(JSON.stringify(data));
  }
};


LB.UI.msgBox = function(msg, to) {
  if( $("#msgbox").length == 0 ) {
    $("#canvasarea").append('<div id="msgbox" class="ui-corner-all"></div>');
    $("#msgbox").hide();
  }

  $("#msgbox").html(msg);
  $("#msgbox").show(2, function(){
                setTimeout(function(){$("#msgbox").fadeOut(500);}, to);
                        });
};


LB.UI.message = function(msg, to) {
  var newdiv = document.createElement('div');
  $(newdiv).addClass("lb-alert ui-corner-all");
  $("#canvasarea").append(newdiv);
  $(newdiv).append('<div>' + msg + '</div>');
  $(newdiv).show(2, function(){
                      setTimeout(
                        function(){
                          $(newdiv).fadeOut(700, 
                            function(){
                              $(newdiv).remove();
                            })
                        }, 
                      to);
                    });
};


LB.UI.alert = function(msg) {
  var newdiv = document.createElement('div');
  $(newdiv).addClass("lb-alert ui-corner-all");
  $("#canvasarea").append(newdiv);
  $(newdiv).append('<div>' + msg + '</div><br><a href="#">Ok</a>');
  var id = $(newdiv).find("a");
  $(id).addClass("ui-btn ui-btn-up-b ui-btn-inner ui-corner-all");
  $(id).bind("vclick", function() { $(newdiv).remove(); });
};


LB.UI.confirm = function(msg, fn) {
  var newdiv = document.createElement('div');
  $("body").append(newdiv);
  $(newdiv).addClass("lb-confirm");

  var str = '<div style="margin: auto; top: 200px; width: 300px; padding: 20px; position: relative;" \
            class="ui-bar-b ui-corner-all"><div>' 
            + msg + 
            '</div><br> \
              <div class="ui-grid-a"> \
                <div class="ui-block-a"> \
                  <a href="#" id="ok" data-role="button" data-theme="b">Ok</a> \
                </div> \
                <div class="ui-block-b"> \
                  <a href="#" id="cancel" data-role="button" data-theme="b">Cancel</a> \
                </div> \
              </div> \
              </div> \
             ';
  $(newdiv).append(str);
  var id = $(newdiv).find("#ok");
  $(id).addClass("ui-btn ui-btn-up-b ui-btn-inner ui-corner-all");
  $(id).bind("vclick", function() { $(newdiv).remove(); });
  var id1 = $(newdiv).find("#cancel");
  $(id1).addClass("ui-btn ui-btn-up-b ui-btn-inner ui-corner-all");
  $(id1).bind("vclick", function() { 
                          fn(); 
                          $(newdiv).remove(); 
                        });
};


//wrapper function to save the id from the created savedialog
LB.UI.savedialog = function() {
  var id = LB.UI.savedialog.create();
  return function() {
    $(id).toggle('fade');
  }
};


//Create a savedialog and return the id, override this if needed
//to create a custom save dialog
LB.UI.savedialog.create = function() {
  var newdiv = document.createElement('div');
  var off = $("#header").offset();
  var height = $("#header").height();
  $(newdiv).addClass("ui-bar-b");
  $(newdiv).css({
                'position': 'absolute',
                'top': off.top+height+1,
                'left': '60%',
                'width': '200px',
                'padding': '20px'
                });
  var str = '<div id="savedialog_id"> \
              <div id="saveform"> \
                Save As: \
                <input type=text id="pagename" class=""></input> \
              </div> \
              <p><a href="#" id="savedialog_save">Save</a></p> \
              <a href="#" id="savedialog_cancel">Cancel</a> \
            </div> \
            ';

  $(newdiv).append(str);
  var id = $(newdiv).find("#savedialog_save");
  $(id).addClass("ui-btn ui-btn-up-b ui-btn-inner ui-corner-all");
  var id1 = $(newdiv).find("#savedialog_cancel");
  $(id1).addClass("ui-btn ui-btn-up-b ui-btn-inner ui-corner-all");

  $(id).bind("vclick", function() { 
                        LB.Book.saveCurrPage($("#pagename").attr('value'));
                        $(newdiv).hide();
                      });
  $(id1).bind("vclick", function() { $(newdiv).hide(); });

  $("body").append(newdiv);
  $(newdiv).hide();
  return newdiv;
};


//********** Utility functions ***********
LB.Utils.getRequestParam = function(name) {
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^?&#]*)";
  var regex = new RegExp( regexS );
  var results = regex.exec( window.location.href );
  if( results == null )
    return "";
  else
    return results[1];
};
